﻿#include "MirrorMgr.h"
#include "CenterService.h"
#include "base/core/com_define.h"
#include "Active/ActiveCharacter.h"
#include "Active/ActiveCharacterMgr.h"
#include "Cache/OfflineCharacterDataMgr.h"
#include "Cache/OfflineCharacterData.h"
#include "base/core/pb_alloc.h"

MirrorMgr::MirrorMgr()
{
	memset(_mirror, 0, sizeof(_mirror));

	head = nullptr;
	tail = nullptr;

	m_pMirrorRole = new ObjectPool < MirrorRole >;

	for (uint32_t i = 0; i < MAX_OFFLINE_USER; ++i)
	{
		MirrorRole* ou = m_pMirrorRole->MallocObj();
		if (nullptr != ou)
		{
			_characterList.push(ou);
		}		
	}
}

MirrorMgr::~MirrorMgr()
{
	MirrorRole* ou = nullptr;
	while (head != NULL)
	{
		ou = head->next[OPTE_LIST];
		if (head != nullptr)
		{
			m_pMirrorRole->FreeObj(head);
		}
		head = ou;
	}
	tail = nullptr;

	uint32_t size = 0;
	while ((size = _characterList.size()) > 0)
	{
		ou = _characterList.top();
		_characterList.pop();
		if (ou != nullptr){
			m_pMirrorRole->FreeObj(ou);
		}
	}

	MMO_DELETE(m_pMirrorRole);
}

bool MirrorMgr::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		MMOLOG_FMT_ERROR("[center] MirrorMgr::Init....nullptr == pMessageDispatch ");
		return false;
	}

	pMessageDispatch->registerDBProxyHandler(EMODULE_ID_MIRROR, this);
	g_GetActiveCharacterMgr()->AddCharacterObserver(this);
	return true;
}

bool MirrorMgr::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr != pMessageDispatch)
	{
		pMessageDispatch->unregisterDBProxyHandler(EMODULE_ID_MIRROR);
	}

	g_GetActiveCharacterMgr()->RemoveCharacterObserver(this);
	return true;
}

void MirrorMgr::Push(CharIDType charId, const CharacterMirrorData& mirrorData)
{
	uint32_t index = HashIndex(charId);

	if (Replace(index, charId, mirrorData))
	{
		return;
	}

	if (!CheckSpace()){
		return;
	}

	MirrorRole* ou = _mirror[index]; // 经过删除节点,哈希表位置的表头可能发生变更,或者遍历,ou要从新指回哈希位置头节点
	MirrorRole* newOu = _characterList.top();
	_characterList.pop();
	newOu->Attach(mirrorData);

	newOu->next[OPTE_CONFLICT] = ou;
	if (ou != nullptr)
	{
		ou->prev[OPTE_CONFLICT] = newOu;
	}
	_mirror[index] = newOu;

	if (tail == nullptr)
	{
		head = tail = newOu;
	}
	else 
	{
		newOu->prev[OPTE_LIST] = tail;
		tail->next[OPTE_LIST] = newOu;
		tail = newOu;
	}
}

bool MirrorMgr::Replace(uint32_t index, CharIDType charId, const CharacterMirrorData& mirrorData)
{
	MirrorRole* ou = _mirror[index];
	while (ou != nullptr)
	{ // 查找替换原有数据
		if (ou->GetCharId() == charId)
		{
			ou->Attach(mirrorData);
			return true;
		}
		ou = ou->next[OPTE_CONFLICT];
	}

	return false;
}

bool MirrorMgr::CheckSpace()
{
	if (_characterList.size() > 0)
	{ // 查找空间，如果没有则释放
		return true;
	}

	if (head == nullptr)
	{
		return false;
	}

	CharIDType charId = head->GetCharId();
	//重新回收空间
	ResetUser(charId);

	return (_characterList.size() > 0);
}

void MirrorMgr::ResetUser(CharIDType charId)
{
	uint32_t index = HashIndex(charId);
	MirrorRole* ou = _mirror[index];
	while (ou != nullptr)
	{
		if (ou->GetCharId() == charId)
		{
			break;
		}
		ou = ou->next[OPTE_CONFLICT];
	}

	if (ou == nullptr)
	{
		return;
	}

	// 哈希链表头需要单独处理
	if (ou == _mirror[index])
	{
		_mirror[index] = ou->next[OPTE_CONFLICT];
	}

	// 先处理哈希表的节点数据
	MirrorRole* prev = ou->prev[OPTE_CONFLICT];
	MirrorRole* next = ou->next[OPTE_CONFLICT];
	if (prev != nullptr)
	{
		prev->next[OPTE_CONFLICT] = next;
	}
	if (next != nullptr)
	{
		next->prev[OPTE_CONFLICT] = prev;
	}

	// 再处理list数据
	prev = ou->prev[OPTE_LIST];
	next = ou->next[OPTE_LIST];
	if (prev == nullptr)
	{
		head = next;
	}
	else 
	{
		prev->next[OPTE_LIST] = next;
	}
	if (next == nullptr)
	{
		tail = prev;
	}
	else {
		next->prev[OPTE_LIST] = prev;
	}

	// 回收数据了
	ou->Detach();
	ou->prev[OPTE_CONFLICT] = NULL;
	ou->prev[OPTE_LIST] = NULL;
	ou->next[OPTE_CONFLICT] = NULL;
	ou->next[OPTE_LIST] = NULL;
	_characterList.push(ou);
}

bool MirrorMgr::LoadCharacterMirrorData(CharIDType charId, uint16_t module, uint16_t protocolCmd, ProtoBufBase* message)
{
	if (g_GetCenterService()->IsConnectDBProxy())
	{
		//开始加载角色镜像数据
		CharacterMirrorDataReq dataReq;
		dataReq.set_charid(charId);
		dataReq.set_reqtypename(message->GetTypeName());
		dataReq.set_cmd(protocolCmd);
		dataReq.set_module(module);
		dataReq.set_data(message->SerializeAsString());

		if (!g_GetCenterService()->SendDataToDBProxy(EMODULE_ID_MIRROR, DBPROXY_PROTOCOL_CHARACTER_MIRROR_DATA_REQ, &dataReq))
		{
			MMOLOG_FMT_ERROR("[center] MirrorMgr::LoadCharacterMirrorData SendDataToDBProxy failed...charId:%llu,module:%d,cmd:%d ", charId,module,protocolCmd);
		}
		else
		{
			return true;
		}
	}
	else
	{
		MMOLOG_FMT_ERROR("[center] MirrorMgr::LoadCharacterMirrorData g_GetCenterService()->IsConnectDBProxy() failed...charId:%llu ", charId);
	}

	return false;
}

void MirrorMgr::onDBProxyMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case DBPROXY_PROTOCOL_CHARACTER_MIRROR_DATA_RSP:
	{
		CharacterMirrorDataRsp rsp;
		if (!rsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
		{
			MMOLOG_FMT_ERROR("[center] CharacterMirrorDataRsp return but parse failed");
			return;
		}

		//将请求回来的镜像数据进行缓存
		Push(rsp.mirrordata().charid(), rsp.mirrordata());
	}
	break;
	default:
		break;
	}
}

void MirrorMgr::onCharacterDel(OfflineCharacterData *pOffLineCharacter)
{
	//删除角色的话要移除该角色的缓存
	if (nullptr != pOffLineCharacter)
	{
		ResetUser(pOffLineCharacter->GetCharID());
	}
}

void MirrorMgr::onCharacterLogout(ActiveCharacter *pOnlineCharacter)
{
	//角色下线的话要移除该角色的缓存
	if (nullptr != pOnlineCharacter)
	{
		ResetUser(pOnlineCharacter->GetCharID());
	}
}

MirrorRole* MirrorMgr::Get(CharIDType charId)
{
	uint32_t index = HashIndex(charId);
	MirrorRole* ou = _mirror[index];
	while (ou != nullptr)
	{
		if (ou->GetCharId() == charId)
		{
			break;
		}
		ou = ou->next[OPTE_CONFLICT];
	}

	return ou;
}